
#ifndef ACTIVATOR_H
#define ACTIVATOR_H

// Std includes.
#include <variant_vector.h>
#include <variant_string.h>

// CSharp includes.
#include <CSharpGarbagePointer.h>
	
// The C# typeof MACRO.
#define typeof(Class) _typeof( Stringize(Class) )

namespace Riccsson
{
	namespace System
	{
		
		class Object;
		class Type;

		typedef void(*_Static_Class_Method)();

		typedef GC_PTR<Object> (*MethodCreateInstance)(void);
		
		// Global typeof method.
		GC_PTR<Riccsson::System::Type> _typeof(const char* className);
	
		class ClassContainer
		{

		private:
			// TODO: Store a function pointer here to create a specific class.
			MethodCreateInstance _functionPointer;

		public:
			const char* _className;

			//------------------------------------------------------------------------------
			// Constructor.
			ClassContainer(MethodCreateInstance method, const char* className)
				: _functionPointer(method)
				, _className(className)
			{
			}

			//------------------------------------------------------------------------------
			GC_PTR<Object> createInstance()
			{
				return _functionPointer(); // Function pointer here.
			}
		};
		
		static const char** _map_keys;
		static ClassContainer** _map_values;
		extern int* _map_values2;
		extern int _map_count;
		extern bool _map_initialized;

		// Summary:
		//     Exposes the System.Activator class to unmanaged code.
		interface _Activator
		{
		};

		// Summary:
		//     Contains methods to create types of objects locally or remotely, or obtain
		//     references to existing remote objects. This class cannot be inherited.
		class Activator sealed : public _Activator
		{
		public:
			static std::map2<const char*, ClassContainer*> _classContainer;
			static int _classIds;

			// Add a registerated class to the activator so it know how to create it dynamically.
			static void _addClass(const char* className, ClassContainer* classContainer);
			
			static void _addStaticClassConstructor(const char* className, _Static_Class_Method classContainer);

			// This method will Riccsson::release() run when the application is shuting down.
			static void _release();

			//
			// Summary:
			//     Creates an instance of the specified type using that type's default constructor.
			//
			// Parameters:
			//   type:
			//     The type of object to create.
			//
			// Returns:
			//     A reference to the newly created object.
			//
			// Exceptions:
			//   System.ArgumentNullException:
			//     type is null.
			//
			//   System.ArgumentException:
			//     type is not a RuntimeType. -or-type is an open generic type (that is, the
			//     System.Type.ContainsGenericParameters property returns true).
			//
			//   System.NotSupportedException:
			//     type cannot be a System.Reflection.Emit.TypeBuilder.-or- Creation of System.TypedReference,
			//     System.ArgIterator, System.Void, and System.RuntimeArgumentHandle types,
			//     or arrays of those types, is not supported.-or-The assembly that contains
			//     type is a dynamic assembly that was created with System.Reflection.Emit.AssemblyBuilderAccess.Save.
			//
			//   System.Reflection.TargetInvocationException:
			//     The constructor being called throws an exception.
			//
			//   System.MethodAccessException:
			//     The caller does not have permission to call this constructor.
			//
			//   System.MemberAccessException:
			//     Cannot create an instance of an abstract class, or this member was invoked
			//     with a late-binding mechanism.
			//
			//   System.Runtime.InteropServices.InvalidComObjectException:
			//     The COM type was not obtained through Overload:System.Type.GetTypeFromProgID
			//     or Overload:System.Type.GetTypeFromCLSID.
			//
			//   System.MissingMethodException:
			//     No matching public constructor was found.
			//
			//   System.Runtime.InteropServices.COMException:
			//     type is a COM object but the class identifier used to obtain the type is
			//     invalid, or the identified class is not registered.
			//
			//   System.TypeLoadException:
			//     type is not a valid type.
			//[SecuritySafeCritical]
			public: static GC_PTR<Object> CreateInstance(Type* type);

			public: template<typename T> static GC_PTR<T> CreateInstance(GC_PTR<Type> type)
			{
				GC_PTR<Object> instance = CreateInstance(type);
				T* str = reinterpret_cast<T*>( (*instance) );
				T* temp = new T(*str);
				return GC_PTR<T>(temp);
			}
		};
	}
}

#endif // ACTIVATOR_H